/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cageballserver;

import cageballcommon.exceptions.CageballIOException;
import cageballcommon.exceptions.CageballMatchException;
import cageballserver.match.Match;
import cageballserver.io.GameServer;
import cageballserver.io.ObserverServer;
import cageballserver.match.MatchExecutor;
import cageballserver.physics.Phys2d;
import cageballserver.physics.PhysicsEngine;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;

/**
 *
 * @author kanonas
 */
public class CageballServer {

    private Properties serverProperties;
    private Properties gameProperties;
    private Properties physicsProperties;
    private GameServer gameServer;
    private ObserverServer observerServer;
    private boolean running;
    private final CageballNotifier notifier;
    private MatchExecutor matchExecutor;

    public CageballServer(Properties serverProperties, Properties gameProperties, Properties physicsProperties, CageballNotifier notifier) {
        this.serverProperties = serverProperties;
        this.gameProperties = gameProperties;
        this.physicsProperties = physicsProperties;
        this.notifier = notifier;

        matchExecutor = new MatchExecutor();

        new Thread(matchExecutor).start();
    }

    public void loadConfigFiles(String server, String game, String physics) throws FileNotFoundException, IOException {
        serverProperties = new Properties();
        gameProperties = new Properties();
        physicsProperties = new Properties();

        serverProperties.load(new FileInputStream(server));
        gameProperties.load(new FileInputStream(game));
        physicsProperties.load(new FileInputStream(physics));
    }

    public void startServer() throws CageballIOException {

        if (!running) {
            try {
                int gamePort = Integer.parseInt(serverProperties.getProperty("gamePort"));
                int observerPort = Integer.parseInt(serverProperties.getProperty("observerPort"));
                gameServer = new GameServer(gamePort, gameProperties, notifier);
                gameServer.start();
                observerServer = new ObserverServer(observerPort);
                observerServer.start();
                running = true;
            } catch (IOException ex) {
                throw new CageballIOException(ex.getMessage());
            }

        } else {
            throw new CageballIOException("Server aldredy running");
        }
    }

    public void stopServer() throws CageballIOException {
        if (running) {
            try {
                gameServer.stop();
                observerServer.stop();
                running = false;
            } catch (IOException ex) {
                throw new CageballIOException(ex.getMessage());
            }
        } else {
            throw new CageballIOException("Server is not running");
        }
    }

    public void restart() throws CageballIOException {
        stopServer();
        try {
            loadConfigFiles("server.properties", "game.properties", "physics.properties");
        } catch (IOException ex) {
            throw new CageballIOException(ex.getMessage());
        }
        startServer();
    }

    public Collection<CageballClient> getClients() {
        return running ? gameServer.listClients() : new ArrayList<CageballClient>();
    }

    public void addMatch(Collection<CageballClient> clients) throws CageballMatchException, CageballIOException {

        PhysicsEngine engine = new Phys2d(physicsProperties);
        matchExecutor.addMatch(new Match(clients, gameProperties, engine, observerServer, gameServer, GameType.Tournament));
    }

    public boolean isRunning() {
        return running;
    }

    public Properties getServerProperties() {
        return serverProperties;
    }

    public Collection<Match> getGameQueue() {
        return matchExecutor.getMatchQueue();
    }
}
